﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace PPSkin
{
    [DefaultEvent("ValueChanged")]
    public partial class PPProgressBar : UserControl
    {
        #region 变量定义

        public event EventHandler ValueChanged;

        private long value = 0;
        private long minimun = 0;
        private long maximun = 100;
        private long step = 1;
        private int radius = 0;
        private bool showTip = false;
        private bool showValue = true;
        private Color baseColor = Color.LightGray;
        private Color valueColor = Color.DodgerBlue;
        private VALUETYPE valueType = VALUETYPE.PERCENT;

        [Description("进度条值"), Category("自定义")]
        public long Value
        {
            get { return value; }
            set
            {
                if (this.value == value)
                    return;
                if (value > maximun)
                {
                    this.value = maximun;
                }
                else if (value < minimun)
                {
                    this.value = minimun;
                }
                else
                {
                    this.value = value;
                }
                if (ValueChanged != null)
                {
                    ValueChanged(this, new EventArgs());
                }
                this.Invalidate();
            }
        }

        [Description("进度条上限"), Category("自定义")]
        public long Maximum
        {
            get { return maximun; }
            set
            {
                if (value < minimun)
                {
                    this.maximun = minimun;
                }
                else
                {
                    this.maximun = value;
                }
            }
        }

        [Description("进度条下限"), Category("自定义")]
        public long Minimum
        {
            get { return minimun; }
            set
            {
                if (value > maximun)
                {
                    this.minimun = maximun;
                }
                else
                {
                    minimun = value;
                }
            }
        }

        [Description("步进增量"), Category("自定义")]
        public long Step
        {
            get { return step; }
            set
            {
                if (value > maximun)
                {
                    step = maximun;
                }
                step = value;
            }
        }

        [Description("是否显示tip"), Category("自定义")]
        public bool ShowTip
        {
            get { return showTip; }
            set
            {
                showTip = value;
            }
        }

        [Description("是否显示进度文字"), Category("自定义")]
        public bool ShowValue
        {
            get { return showValue; }
            set
            {
                showValue = value;
            }
        }

        [Description("圆角半径"), Category("自定义")]
        public int Radius
        {
            get { return radius; }
            set
            {
                if (value < 0 || value > Math.Min(this.Width, this.Height))
                    return;
                radius = value;
                //this.Region = new Region(CreateRound(new Rectangle(0, 0, this.Width, this.Height), radius));
            }
        }

        [Description("底色"), Category("自定义")]
        public Color BaseColor
        {
            get { return this.baseColor; }
            set
            {
                this.baseColor = value;
            }
        }

        [Description("有值的颜色"), Category("自定义")]
        public Color ValueColor
        {
            get { return this.valueColor; }
            set
            {
                this.valueColor = value;
            }
        }

        [Description("文字显示类型，数值和百分比"), Category("自定义")]
        public VALUETYPE ValueType
        {
            get { return valueType; }
            set
            {
                valueType = value;
            }
        }

        public enum VALUETYPE
        {
            VALUE,
            PERCENT,
        }

        #endregion 变量定义

        public Enums.DrawMode TextDrawMode { get; set; } = Enums.DrawMode.Clear;

        public PPProgressBar()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.SetStyle(ControlStyles.Selectable, true);
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.SetStyle(ControlStyles.UserPaint, true);
            this.ValueChanged += new EventHandler(this.Value_Changed);
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            //this.Region = new Region(CreateRound(new Rectangle(0, 0, this.Width, this.Height), radius));
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            if (radius > Math.Min(this.Width, this.Height))
            {
                radius = Math.Min(this.Width, this.Height);
            }
            //this.Region = new Region(CreateRound(new Rectangle(0, 0, this.Width, this.Height), radius));
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Graphics g = e.Graphics;
            g.SmoothingMode = radius==0? System.Drawing.Drawing2D.SmoothingMode.Default:SmoothingMode.AntiAlias;
            g.TextRenderingHint = TextDrawMode == Enums.DrawMode.Anti ? System.Drawing.Text.TextRenderingHint.AntiAlias : System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
            g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            float percent = (float)Math.Round((decimal)this.value / (this.maximun - this.minimun), 2);

            Brush baseBrush = new SolidBrush(baseColor);
            Brush valueBrush = new SolidBrush(valueColor);
            Brush backBrush = new SolidBrush(BackColor);

            GraphicsPath basePath = PaintHelper.CreatePath(new Rectangle(0, 0, this.Width, this.Height), radius);
            g.FillPath(baseBrush, basePath);

            Rectangle valueRect = new Rectangle((int)(-1 * (1 - percent) * (this.Width - 1)), 0, this.Width, this.Height);
            GraphicsPath valeupath = PaintHelper.CreatePath(valueRect, radius,Enums.RoundStyle.Left);
            g.FillPath(valueBrush, valeupath);

            if (showValue)
            {
                string text = (100 * percent).ToString() + "%";
                if (valueType == VALUETYPE.VALUE)
                {
                    text = value.ToString();
                }
                SizeF size = g.MeasureString(text, this.Font);
                Brush textBrush = new SolidBrush(this.ForeColor);
                g.DrawString(text, this.Font, textBrush, new Point(this.Width / 2 - (int)size.Width / 2 - 1, this.Height / 2 - (int)size.Height / 2 + 2));
                textBrush.Dispose();
            }
            basePath.AddRectangle(new Rectangle(-1, -1, this.Width + 1, this.Height + 1));
            
            g.FillPath(backBrush, basePath);

            baseBrush.Dispose();
            valueBrush.Dispose();
            backBrush.Dispose();
            basePath.Dispose();
            valueBrush.Dispose();

            //g.DrawPath(new Pen(this.BackColor,1f),PaintHelper.CreateRound(new Rectangle(1, 1, this.Width-1, this.Height-1), radius));
        }

        protected override void OnVisibleChanged(EventArgs e)
        {
            base.OnVisibleChanged(e);
            if (!Visible)
            {
                if (frmTips != null && !frmTips.IsDisposed)
                {
                    frmTips.Close();
                    frmTips = null;
                }
            }
        }

        private void Value_Changed(object sender, EventArgs e)
        {
            ShowTips();
        }

        public void AddStep()
        {
            if (value + step > maximun)
            {
                Value = maximun;
            }
            else
            {
                Value += step;
            }
        }

        public void ReduceStep()
        {
            if (value - step < minimun)
            {
                Value = minimun;
            }
            else
            {
                Value -= step;
            }
        }

        [Description("获取当前进度条百分比0-1")]
        public float GetPercentValue()
        {
            float percent = (float)Math.Round((decimal)this.value / (this.maximun - this.minimun), 2);
            return percent;
        }

        private FrmAnchorTips frmTips = null;

        private void ShowTips()
        {
            if (showTip)
            {
                float percent = (float)Math.Round((decimal)this.value / (this.maximun - this.minimun), 2);
                Rectangle rect = new Rectangle((int)(percent * this.Width) - 5, 0, 5, this.Height);
                string text = (100 * percent).ToString() + "%";
                if (valueType == VALUETYPE.VALUE)
                {
                    text = value.ToString();
                }

                var p = this.PointToScreen(new Point(rect.X, rect.Y));

                if (frmTips == null || frmTips.IsDisposed || !frmTips.Visible)
                {
                    frmTips = FrmAnchorTips.ShowTips(new Rectangle(p.X, p.Y, rect.Width, rect.Height), text, this.Font.Name, (int)this.Font.Size, AnchorTipsLocation.TOP, ValueColor, ForeColor, autoCloseTime: -1);
                }
                else
                {
                    frmTips.RectControl = new Rectangle(p.X, p.Y, rect.Width, rect.Height);
                    frmTips.StrMsg = text;
                }
            }
        }
    }
}